#include "video_renderer.h"
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/sdp/sdp.h>
#include <gst/webrtc/webrtc.h>
#include <libsoup/soup.h>
#include <json-glib/json-glib.h>
#include <gio/gio.h>
#include <stdio.h>
#include <string.h>

static GstElement *pipeline = NULL;
static GstElement *appsrc = NULL;
static SoupWebsocketConnection *ws_conn = NULL;
static GMainLoop *main_loop = NULL;

#define WS_URL "ws://192.168.100.25:8443"

static void send_json(JsonBuilder *builder);
static void setup_webrtc_signaling();

static gpointer webrtc_loop_thread(gpointer user_data) {
    main_loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(main_loop);
    return NULL;
}

static void send_json(JsonBuilder *builder) {
    JsonGenerator *gen = json_generator_new();
    JsonNode *root = json_builder_get_root(builder);
    json_generator_set_root(gen, root);
    gchar *text = json_generator_to_data(gen, NULL);
    g_print("\U0001F4E8 发送 JSON: %s\n", text);
    soup_websocket_connection_send_text(ws_conn, text);
    g_free(text);
    g_object_unref(gen);
    json_node_free(root);
}

static void on_ws_message_cb(SoupWebsocketConnection *conn, SoupWebsocketDataType type, GBytes *msg, gpointer user_data) {
    gsize size;
    const gchar *data = g_bytes_get_data(msg, &size);
    JsonParser *parser = json_parser_new();
    if (!json_parser_load_from_data(parser, data, size, NULL)) return;
    JsonObject *obj = json_node_get_object(json_parser_get_root(parser));
    const gchar *type_str = json_object_get_string_member(obj, "type");

    if (g_strcmp0(type_str, "register") == 0) {
        const gchar *role = json_object_get_string_member(obj, "role");
        g_print("\U0001F9E0 收到 register: %s\n", role);
    }

    g_object_unref(parser);
}

static void on_ws_connected_cb(GObject *source, GAsyncResult *res, gpointer user_data) {
    GError *error = NULL;
    ws_conn = soup_session_websocket_connect_finish(SOUP_SESSION(source), res, &error);
    if (!ws_conn) {
        g_printerr("❌ WebSocket 连接失败: %s\n", error->message);
        g_error_free(error);
        return;
    }
    g_signal_connect(ws_conn, "message", G_CALLBACK(on_ws_message_cb), NULL);

    JsonBuilder *b = json_builder_new();
    json_builder_begin_object(b);
    json_builder_set_member_name(b, "type");
    json_builder_add_string_value(b, "register");
    json_builder_set_member_name(b, "role");
    json_builder_add_string_value(b, "streamer");
    json_builder_end_object(b);
    send_json(b);
    g_object_unref(b);
    g_print("\U0001F4E4 Streamer 注册消息已发送\n");
}

static void setup_webrtc_signaling() {
    SoupSession *session = soup_session_new();
    SoupMessage *msg = soup_message_new(SOUP_METHOD_GET, WS_URL);
    soup_session_websocket_connect_async(session, msg, NULL, NULL, 0, NULL, on_ws_connected_cb, NULL);
}

static void webrtc_renderer_start(video_renderer_t *renderer) {
    gst_init(NULL, NULL);

    pipeline = gst_parse_launch(
        "appsrc name=mysrc is-live=true block=true format=3 do-timestamp=true "
        "caps=video/x-h264,stream-format=byte-stream,alignment=au ! "
        "h264parse config-interval=1 ! matroskamux ! filesink location=output.mkv", 
        NULL);

    appsrc = gst_bin_get_by_name(GST_BIN(pipeline), "mysrc");

    GstCaps *caps = gst_caps_from_string("video/x-h264,stream-format=byte-stream,alignment=au");
    gst_app_src_set_caps(GST_APP_SRC(appsrc), caps);
    gst_caps_unref(caps);

    gst_element_set_state(pipeline, GST_STATE_PLAYING);
    g_print("✅ WebRTC pipeline started\n");

    if (!main_loop)
        g_thread_new("webrtc-loop", webrtc_loop_thread, NULL);

    if (!ws_conn)
        setup_webrtc_signaling();
}

static void webrtc_renderer_render(video_renderer_t *renderer, raop_ntp_t *ntp, unsigned char *data, int data_len, uint64_t pts, int type) {
    static FILE *rawdump = NULL;
    if (!rawdump) rawdump = fopen("dumped.h264", "wb");
    fwrite(data, 1, data_len, rawdump);
    fflush(rawdump);

    if (!appsrc || !data || data_len < 5) return;

    int nal_unit_type = (data[4] & 0x1F);

    GstBuffer *buffer = gst_buffer_new_allocate(NULL, data_len, NULL);
    gst_buffer_fill(buffer, 0, data, data_len);

    static uint64_t frame_counter = 0;
    GST_BUFFER_PTS(buffer) = frame_counter * GST_SECOND / 30;
    GST_BUFFER_DTS(buffer) = frame_counter * GST_SECOND / 30;
    GST_BUFFER_DURATION(buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 30);
    frame_counter++;

    if (nal_unit_type == 5 || nal_unit_type == 7 || nal_unit_type == 8) {
        GST_BUFFER_FLAG_UNSET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
    } else {
        GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
    }

    GstFlowReturn ret = gst_app_src_push_buffer(GST_APP_SRC(appsrc), buffer);
    if (ret != GST_FLOW_OK) {
        g_printerr("❌ push buffer 失败: %d\n", ret);
    } else {
        g_print("✅ buffer 成功推入 pipeline，类型=%d 大小=%d\n", nal_unit_type, data_len);
    }
}

static void webrtc_renderer_destroy(video_renderer_t *renderer) {
    if (pipeline) {
        gst_element_set_state(pipeline, GST_STATE_NULL);
        gst_object_unref(pipeline);
        pipeline = NULL;
    }
    appsrc = NULL;
}

static void webrtc_renderer_update_background(video_renderer_t *renderer, int show) {
    g_printerr("🧱 WebRTC renderer background update: show=%d (忽略)\n", show);
}

video_renderer_t *get_video_renderer_webrtc() {
    static video_renderer_t r;
    static video_renderer_funcs_t funcs = {
        .start = webrtc_renderer_start,
        .render_buffer = webrtc_renderer_render,
        .flush = NULL,
        .destroy = webrtc_renderer_destroy,
        .update_background = webrtc_renderer_update_background
    };
    memset(&r, 0, sizeof(r));
    r.funcs = &funcs;
    return &r;
}
